#if defined(TSINGMA_MX) || defined(TSINGMA_GX) || defined(ARCTIC)

#include "ctc_error.h"
#include "sys_usw_common.h"
#include "sys_usw_mirror.h"
#include "sys_usw_register.h"

extern sys_mirror_master_t* p_usw_mirror_master[CTC_MAX_LOCAL_CHIP_NUM_PP];

int32
sys_tmm_mirror_set_dst_to_linkagg(uint8 lchip, void* met_fifo_excp, uint32* member_list, uint16 member_cnt, uint8 is_set)
{
    uint16 lport = 0;
    uint8  gchip_id = 0, chip_id = 0;
    uint8  trunk_id = 0;
    uint8  loop = 0;
    uint8  step = DsMetFifoExcp_u_g1_member1_f - DsMetFifoExcp_u_g1_member0_f;

    for (loop = 0; loop < 8; loop++)
    {
        SetDsMetFifoExcp(V, u_g1_destSgmacGroupId0_f + loop, met_fifo_excp, 0);
        SetDsMetFifoExcp(V, u_g1_member0_f + loop*step, met_fifo_excp, 0);
    }
    SetDsMetFifoExcp(V, u_g1_memberNum_f, met_fifo_excp, 0);
    SetDsMetFifoExcp(V, unionDestType_f, met_fifo_excp, 0);

    if (is_set)
    {
        CTC_ERROR_RETURN(sys_usw_get_gchip_id(lchip, &gchip_id));
        for (loop=0; loop<member_cnt; loop++)
        {
            lport = CTC_MAP_GPORT_TO_LPORT(member_list[loop]);
            chip_id = CTC_MAP_GPORT_TO_GCHIP(member_list[loop]);
            if ((chip_id != gchip_id) && !SYS_CB_PTR(SYS_CB_STK_GET_TRUNK_BY_RCHIP))
            {
                SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "  Stacking not support!  \n");
                return CTC_E_NOT_SUPPORT;
            }
            else if (chip_id != gchip_id)
            {
                SYS_CB(SYS_CB_STK_GET_TRUNK_BY_RCHIP, lchip, chip_id, &trunk_id);

                SetDsMetFifoExcp(V, u_g1_destSgmacGroupId0_f+loop, met_fifo_excp, trunk_id);
            }
            SetDsMetFifoExcp(V, u_g1_member0_f+loop*step, met_fifo_excp, SYS_ENCODE_DESTMAP(chip_id, lport));
        }
        if (member_cnt == 0)
        {
            SetDsMetFifoExcp(V, u_g1_member0_f, met_fifo_excp,MCHIP_CAP(SYS_CAP_RSV_PORT_DROP_ID));
            SetDsMetFifoExcp(V, u_g1_memberNum_f, met_fifo_excp, member_cnt);
        }
        else
        {
            SetDsMetFifoExcp(V, u_g1_memberNum_f, met_fifo_excp, member_cnt - 1);
        }
        SetDsMetFifoExcp(V, unionDestType_f, met_fifo_excp, 1);
    }

    return CTC_E_NONE;
}

int32 
_sys_tmm_mirror_traverse_linkagg_member(sys_mirror_dest_node_t* bucket_data, void* user_data)
{
    int32  ret = CTC_E_NONE;
    uint8  ctc_session_type = 0, acl_prio = 0;
    uint32 excp_index = 0;
    uint32 cmd = 0;
    DsMetFifoExcp_m met_excp;
    ctc_mirror_dest_t mirror;
    uint8 gchip_id;
    sys_mirror_dest_node_t* dest_node = bucket_data;
    sys_traverse_t* p_user_data = (sys_traverse_t*)user_data;
    uint32* member_list = (uint32*)(p_user_data->data);
    uint16 tid = p_user_data->value1;
    uint16 member_cnt = p_user_data->value2; 
    uint8 is_set = p_user_data->value3;
    uint8 lchip = p_user_data->value4;
    if ((SYS_MIRROR_RSPAN_OVER_LINKAGG != dest_node->data_type && SYS_MIRROR_SPAN_OVER_LINKAGG != dest_node->data_type) 
        || tid != dest_node->linkagg_id)
    {
        return 0;
    }
    
    mirror.dir = dest_node->dir;
    sys_usw_mirror_type_unmapping(dest_node->type, &ctc_session_type, &acl_prio);
    
    mirror.acl_priority = acl_prio;
    mirror.type = ctc_session_type;
    mirror.session_id = dest_node->session_id;
    ret = sys_usw_mirror_mapping_excp_index(lchip, &mirror, &excp_index, dest_node->member_index);
    
    if (ret != CTC_E_NONE)
    {
        return 0;
    }
    cmd = DRV_IOR(DsMetFifoExcp_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, excp_index, cmd, &met_excp);
    ret = sys_tmm_mirror_set_dst_to_linkagg(lchip, &met_excp, member_list, member_cnt, is_set);
    if (ret != CTC_E_NONE)
    {
        return 0;
    }
    
    /* is_set indicate add/remove member, !is_set indicate remove group */
    if (!is_set)
    {
        if (SYS_MIRROR_RSPAN_OVER_LINKAGG == dest_node->data_type)
        {
            dest_node->data_type = SYS_MIRROR_RSPAN_OVER_VLAN;
            dest_node->linkagg_id = 0;
        }
        else
        {
            ret = 1;
            mem_free(dest_node);
        }
        
        sys_usw_get_gchip_id(lchip, &gchip_id);
        SetDsMetFifoExcp(V, destMap_f, &met_excp, SYS_ENCODE_DESTMAP(gchip_id, SYS_RSV_PORT_DROP_ID));
    }
    cmd = DRV_IOW(DsMetFifoExcp_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, excp_index, cmd, &met_excp);
    return ret;
}


int32
sys_tmm_mirror_update_linkagg_member(uint8 lchip, uint16 tid, uint32* member_list, uint16 member_cnt, uint8 is_set)
{
    sys_traverse_t user_data;
    sal_memset(&user_data,0,sizeof(sys_traverse_t));
    user_data.data = member_list;
    user_data.value1 = tid;
    user_data.value2 = member_cnt;
    user_data.value3 = is_set;
    user_data.value4 = lchip;
    
    ctc_hash_traverse_remove(p_usw_mirror_master[lchip]->dest_hash, 
                         (hash_traversal_fn)_sys_tmm_mirror_traverse_linkagg_member, (void*)(&user_data));

    return CTC_E_NONE;
}

#endif

